#pragma once

#ifndef NAMESPACE_BEGIN
	#define NAMESPACE_BEGIN(ns) \
	namespace ns{
	#define NAMESPACE_END() \
	}
#endif

#ifndef CHECK_BEGIN
	#define CHECK_BEGIN()	NAMESPACE_BEGIN(_check)
	#define CHECK_END()	NAMESPACE_END()
#endif

#ifndef DUMMY_BEGIN
	#define DUMMY_BEGIN()	NAMESPACE_BEGIN(_dummy)
	#define DUMMY_END()	NAMESPACE_END()
#endif

#ifndef MID_BEGIN
	#define MID_BEGIN()	NAMESPACE_BEGIN(_mid)
	#define MID_END()	NAMESPACE_END()
#endif

#ifndef ERRROR_BEGIN
	#define ERRROR_BEGIN()	NAMESPACE_BEGIN(_error)
	#define ERROR_END()	NAMESPACE_END()
#endif

#ifndef IID_BEGIN
	#define IID_BEGIN()	NAMESPACE_BEGIN(_iid)
	#define IID_END()	NAMESPACE_END()
#endif

#ifndef CLSID_BEGIN
#define CLSID_BEGIN()	NAMESPACE_BEGIN(_clsid)
#define CLSID_END()	NAMESPACE_END()
#endif

#ifndef SYS_BEGIN
#define SYS_BEGIN()	NAMESPACE_BEGIN(sys)
#define SYS_END()	NAMESPACE_END()
#endif

#ifndef DONT_NEW
#define DONT_NEW()  \
	private: \
	static void* operator new(size_t,_dummy::Dumy);
#endif

#ifndef CHECK_RETURN
	#define CHECK_RETURN(exp)	 \
			const vresult _result=(exp); \
			if(_result!=vok) \
			return _result; 
#endif

#ifndef DEFINE_IDSPACE
#define DEFINE_IDSPACE(moduleName,mid) \
	MID_BEGIN() \
	template<> struct MID_T<(uint32)(mid)> { \
		enum{ code=((uint32)(mid) & 0xFFFFFF00ul)}; \
		enum{ checkByteBe0=_check::Check<(mid&0x000000FF)==0>::check};\
	};\
	MID_END()\
	const moduleid moduleName(_mid::MID_T<(uint32)(mid)>::code);
#endif//DEFINE_IDSPACE

#ifndef DEFINE_ERROR
#define DEFINE_ERROR(codeName,moduleID,errOffset) \
	ERRROR_BEGIN() \
	template<> struct ECODE_T<(vresult)((moduleID)+(errOffset))> { \
		enum{ code=(vresult)((moduleID)+(errOffset))}; \
		}; \
	ERROR_END() \
	const vresult codeName(_error::ECODE_T<(vresult)((moduleID)+(errOffset))>::code);
#endif//DEFINE_ERROR

#ifndef DEFINE_IID_CONST
#define DEFINE_IID_CONST(iidName,mid,iidOffset) \
	IID_BEGIN() \
	template<> struct IID_T<MAKE_IID(mid,iidOffset)> { \
	enum{ code=MAKE_IID(mid,iidOffset),}; \
	enum{ checkMidByteBe0=_check::Check<(mid&0x000000FF)==0>::check, \
	checkOffsetBeByte=_check::Check<(iidOffset&0xFFFFFF00)==0>::check,}; \
	}; \
	IID_END() \
	const viid iidName(_iid::IID_T<MAKE_IID(mid,iidOffset)>::code);
#endif//DEFINE_IID_CONST

#ifndef DEFINE_CLSID_CONST
#define DEFINE_CLSID_CONST(clsIDName,mid,clsIDOffset) \
	CLSID_BEGIN() \
	template<> struct CLSID_T<MAKE_IID(mid,clsIDOffset)> { \
	enum{ code=MAKE_IID(mid,clsIDOffset),}; \
	enum{ checkMidByteBe0=_check::Check<(mid&0x000000FF)==0>::check, \
	checkOffsetBeByte=_check::Check<(clsIDOffset&0xFFFFFF00)==0>::check};\
		}; \
		CLSID_END() \
		const vclsid clsIDName(_clsid::CLSID_T<MAKE_CLSID(mid,clsIDOffset)>::code);
#endif//DEFINE_CLSID_CONST
///////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////
//check
CHECK_BEGIN()
template<bool>
struct Check{};
template<>
struct Check<true>{enum{check=1};};
CHECK_END()

MID_BEGIN()
template<uint32 mid>
struct MID_T{};
MID_END()

DUMMY_BEGIN()
struct Dumy{ Dumy(Dumy&,Dumy&); };
DUMMY_END()

ERRROR_BEGIN()
template<vresult vr>
struct ECODE_T{};
ERROR_END()

IID_BEGIN()
template<viid iid>
struct IID_T{};
IID_END()

CLSID_BEGIN()
template<vclsid clsID>
struct CLSID_T{};
CLSID_END()
///////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////

#define BEGIN_DEFINE_CLASS(thisclsID)  \
	DEFINE_CLSID(thisclsID) \
	vresult DoQueryInterface(viid iid,IInterface** ppV) \
	{ \
		ASSERT(ppV && (*ppV)==NULL); \
		while(DoQueryInterfaceInThisClass(iid,ppV)) \
		{ \
			return vok; \
		} \
		return err_notsupport; \
	} \
	bool DoQueryInterfaceInThisClass(viid iid,IInterface** ppV) \
	{ \
		UNREFERENCED_PARAMETER(iid); \
		UNREFERENCED_PARAMETER(ppV); 

#define DEFINE_INTERFACE_ENTRY(IF_Type) \
		while(iid==IF_Type::IID_IF) \
		{ \
			*ppV=static_cast<IInterface*>(static_cast<IF_Type*>(this)); \
			(*ppV)->IncInterfaceRef(); \
			return true; \
		}

#define USE_INTERFACE_ENTRY(CLASS) \
		while(CLASS::DoQueryInterfaceInThisClass(iid,ppV)) \
		{ \
			return true; \
		}

#define DEFINE_INTERFACE_ENTRY_aggregate(IF_Type,AGGR_Object) \
		while(iid==IF_Type::IID_IF && AGGR_Object.DoQueryInterfaceInThisClass(iid,ppV)) \
		{ \
			return true; \
		}

#define USE_INTERFACE_ENTRY_aggregate(AGGR_Object) \
		while(AGGR_Object.DoQueryInterfaceInThisClass(iid,ppV)) \
		{ \
			return true; \
		}

#define END_DEFINE_CLASS() \
		return false; \
	}

#define AUTO_REGISTER_CLASSMAP_ENTRY(classname)\
	static sys::auto_register_assistant _register##classname##(##classname##::CLSID_CLS,&sys::Object<##classname##>::CreateMe);

#define AUTO_REGISTER_CLASSMAP_ENTRY_singleton(classname)\
	static sys::auto_register_assistant _register##classname##(##classname##::CLSID_CLS,&sys::SingletonObject<##classname##>::CreateMe);

#define AUTO_REGISTER_CLASSMAP_ENTRY_addin(classname)\
	extern "C" EXPORT_API vclsid getAddinClass(){return classname##::CLSID_CLS;}\
	static sys::auto_register_assistant _register##classname##(##classname##::CLSID_CLS,&sys::SingletonObject<##classname##>::CreateMe);
